﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_Components.h".
//-------------------------------------------------------------------
/*
	Description:
			[ru]	Содержит классы по моделированию полета пули.
*/

#ifndef _UXS_BALLISTICS_H
#define _UXS_BALLISTICS_H

#pragma once

#include "Constants.h"

namespace UX_STL
{
namespace UXPhysics
{


	//
	// Ballistics
	//

	namespace Ballistics
	{
		struct Utils;


		//
		// Atmosphere Parameters
		//

		struct TAtmosphere
		{
			fvec3	vWindDir;		// wind velocity direction
			fvec3	vGravityDir;	// direction of gravitational acceleration
			float	fPressure,		// (Pa)
					fT,				// temperature (C)
					fAirHumidity,	// 0..1
					fWindVel,		// wind velocity (m/s)
					fGravity;		// (m/s*s)
			///
			TAtmosphere():
				vGravityDir(0.f, 0.f, -1.f), vWindDir(0.f, 1.f, 0.f), fPressure(0.f),
				fT(0.f), fAirHumidity(0.f), fGravity(0.f), fWindVel(0.f)
			{}
		};



		//
		// Cartridge
		//

		struct TCartridge
		{
			string		sInfo;
			fvec3		vBC;
			fvec2		vPower;				// V = Power0 / barrel_length + Power1	// initial velocity
			float		fCaliber,			// bullet caliber (m)
						fMass,				// cartridge mass (kg)
						fBulletMass,		// bullet mass (kg)
						fBulletLength,		// bullet length (m)
						fIVDeviation,		// deviation of the initial velocity (0..1)
						fTempSens,			// V = V * (1 + (0 - temperature) * K)
						fAForce;			// ascensional force (m/s*s)
			///
			TCartridge(): fCaliber(0.f), fMass(0.f), fBulletMass(0.f), fBulletLength(0.f), fIVDeviation(0.001f) {}

			TCartridge(const fvec3 &bc, const fvec2 &vPow, float cal, float mass, float bulmass,
				   float bullength, float ivdev, float tsens, float force, const string &info):
				sInfo(info), vBC(bc), vPower(vPow), fCaliber(cal),
				fMass(mass), fBulletMass(bulmass), fBulletLength(bullength),
				fIVDeviation(ivdev), fTempSens(tsens), fAForce(force)
			{}
		};



		//
		// Bullet
		//

		struct UX_EXPORT TBullet
		{
			friend struct Ballistics::Utils;

		private:
			TCartridge const &	_sCartridge;
			fvec3				_vDirection;	// initial direction of velocity
			float				_fVelocity,		// (m/s)
								_fGravity;		// (m/s)
	
			static const double	_s_dTimeStep;
			static const float	_s_fPowerB;		// V = P0/(L+B) + P1

		public:
			TBullet(const TCartridge &sCartridge, const fvec3 &vDir, float fBarrelLength);
			
			void Update(const TAtmosphere &sAtm, float fTimeDelta, fvec3 &vDelta);

			fvec3 const &		Direction()		const	{ return _vDirection; }
			fvec3 &				Direction()				{ return _vDirection; }
			float				Velocity()		const	{ return _fVelocity; }
			float &				Velocity()				{ return _fVelocity; }
			TCartridge const &	Cartridge()		const	{ return _sCartridge; }
		};



		//
		// Default Cartridges
		//

		struct UX_EXPORT DefaultCartridge
		{
			enum ECartridge
			{
				UNKNOWN		= 0,

				// 5.45
				S_545_39_PS,		// 5.45x39 7Н6 (ПС)
				S_545_39_PP,		// 5.45x39 7Н10 (ПП)
				S_545_39_BP,		// 5.45x39 7Н22 (БП)
				
				// 7.62
				S_762_39_PS,		// 7.62x39 57-Н-231 (ПС)
				S_762_39_US,		// 7.62x39 57-Н-231У (УС)
				S_762_54_LPS,		// 7.62x54 57-Н-323 (ЛПС)
				
				// 12.7
				S_127_108_B32,		// 12.7x108 Б-32
			};

			struct TExtCartridge
			{
				TCartridge	sCartridge;
				ECartridge	eType;
				///
				TExtCartridge(): eType(UNKNOWN) {}
				TExtCartridge(const TCartridge &sh, ECartridge type): sCartridge(sh), eType(type) {}
			};

			static void Init();
			static bool Add(ECartridge eType, const TCartridge &sCartridge);
			static bool Get(ECartridge eType, TCartridge &sCartridge);
			static void DefAtmosphere(TAtmosphere &sAtm);

		private:
			static array< TExtCartridge >	_s_aCartridges;
		};



		//
		// Utilites
		//

		struct UX_EXPORT Utils
		{
			static void CalcBC(TCartridge &sCartridge, const uni_array<float> &aVelocities,
								const uni_array<float> &aFlyTimes, float fStep, const TAtmosphere &sAtm);

			static void CalcAscensionalForce(TCartridge &sCartridge, float fHeightDelta, float fTimeDelta, const TAtmosphere &sAtm);

			static void CalcPower(TCartridge &sCartridge, const fvec2 &aV, const fvec2 &aBarrel);
			
			static void Simulate(const TCartridge &sCartridge, float fBarrel, const TAtmosphere &sAtm,
								 float fDistance, float &fTime, float &fHeight, float &fVelocity);

			static void ZeroToDist(const TCartridge &sCartridge, float fBarrel, const TAtmosphere &sAtm,
									float fDistance, /*inout*/fvec3 &vDirection);

			static float HeightCorrection(float fSightingLineHeight, float fZeroToDist, float fDistance);
		};

	}	// Ballistics

//-------------------------------------------------------------------

}	// UXPhysics
}	// UX_STL

#endif	// _UXS_BALLISTICS_H